package service

import (
	"devops/models"
	"errors"
	"fmt"
	"strconv"

	tsf "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tsf/v20180326"
)

// 创建持续部署计划
func (d *devOps) CreateCD(cid int, groupID string) error {
	if ci := models.GetCIByID(cid); ci == nil {
		models.DeleteCD(cid)
		return errors.New("构建计划不存在")
	}
	var err error
	_, err = d.GetGroupDetail(groupID)
	if err != nil {
		return err
	}
	cdData := models.Cd{CId: cid, GroupId: groupID, DeployResult: "UNKNOWN"}
	if cd := models.GetCD(cid); cd.ID == 0 {
		err = models.CreateCD(cdData)
	} else {
		err = models.UpdateCD(cid, cdData)
	}
	return err
}

func (d *devOps) GetCD(buildID int) models.Cd {
	return models.GetCdByBuildID(buildID)
}

// 获取可用部署组
//func (d *devOps) GetDeployGroups(cid int) ([]*tsf.ContainGroup, error) {
//	imageEnv := models.GetCiEnv(models.CiEnv{CId: cid, Name: "DOCKER_IMAGE_NAME"})
//	if imageEnv.Default == "" {
//		return nil, errors.New("构建计划未设置镜像")
//	}
//	apps, err := d.GetApplications(imageEnv.Default, "")
//	if err != nil || len(apps.Response.Result.Content) < 1 {
//		return nil, errors.New("应用不存在")
//	}
//	groups, err := d.GetContainerGroups(*apps.Response.Result.Content[0].ApplicationId)
//	if err != nil {
//		return nil, err
//	}
//	return groups.Response.Result.Content, nil
//}
//
//func (d *devOps) GetDeployGroups(appName string) {
//
//}

func (d *devOps) InsertCD(cid int, buildID int) {
	if imageEnv := models.GetCiEnv(models.CiEnv{CId: cid, Name: "DOCKER_IMAGE_NAME"}); imageEnv.Default == "" {
		// 未设置镜像，不用cd
		return
	}
	cd := models.GetCD(cid)
	models.CreateCD(models.Cd{
		CId:          cid,
		BuildID:      buildID,
		GroupId:      cd.GroupId,
		DeployResult: "UNKNOWN",
	})
}

// 有新的构建记录时候， 查看是否需要更新 cd 的 build id
func (d *devOps) UpdateBuildID(cid int, buildID int) {
	if imageEnv := models.GetCiEnv(models.CiEnv{CId: cid, Name: "DOCKER_IMAGE_NAME"}); imageEnv.Default == "" {
		// 未设置镜像，不用cd
		return
	}
	cd := models.GetCD(cid)
	if buildID < cd.BuildID {
		return
	}
	models.UpdateCD(cid, models.Cd{BuildID: buildID, DeployResult: "UNKNOWN"})
}

func (d *devOps) RestartDeployGroup(build *models.Build) {
	if build == nil {
		return
	}
	if build.Result != "SUCCESS" {
		return
	}
	cd := models.GetLastCDByCID(build.CID)
	// 比持续集成的build id 小， 不理会
	if build.ID < cd.BuildID {
		return
	}

	// id 相等 并且 部署结果是正确的， 不理会
	if build.ID == cd.BuildID && (cd.DeployResult == "true" || cd.DeployResult == "Running") {
		return
	}
	// 获取部署组信息
	group, err := d.GetGroupDetail(cd.GroupId)
	if err != nil {
		models.UpdateOneCD(build.CID, models.Cd{BuildID: build.ID, DeployResult: "false", Log: fmt.Sprintf("部署组 %s 不存在\n error: %s \n", cd.GroupId, err.Error())})
		return
	}
	repoName, tagName, server := d.GetDeployGroupRestartParam(*build)
	result, err := d.DeployGroup(group.Response.Result, repoName, tagName, server)
	if err != nil {
		models.UpdateOneCD(build.CID, models.Cd{BuildID: build.ID, DeployResult: "false", Log: fmt.Sprintf("部署组 %s 任务下发失败\n error: %s \n", cd.GroupId, err.Error())})
		return
	}
	models.UpdateOneCD(build.CID, models.Cd{BuildID: build.ID, DeployResult: strconv.FormatBool(*result.Response.Result), Log: fmt.Sprintf("部署组 %s 任务下发成功 \n", cd.GroupId)})
}

// 重启部署组
func (d *devOps) DeployGroup(detail *tsf.ContainerGroupDetail, repoName string, tagName string, server string) (*tsf.DeployContainerGroupResponse, error) {

	request := tsf.NewDeployContainerGroupRequest()

	// 部署组ID
	request.GroupId = detail.GroupId

	// 资源限制
	request.CpuRequest = detail.CpuRequest
	request.CpuLimit = detail.CpuLimit
	request.MemRequest = detail.MemRequest
	request.MemLimit = detail.MemLimit

	// 启动实例
	var defaultInstanceNum int64 = 1
	if detail.InstanceNum == nil || *detail.InstanceNum < 1 {
		detail.InstanceNum = &defaultInstanceNum
	}
	request.InstanceNum = detail.InstanceNum

	// 镜像相关
	request.RepoName = &repoName
	request.Server = &server
	request.TagName = &tagName

	return d.tsfClient.DeployContainerGroup(request)
}

func (d *devOps) UpdateDeployGroupsStatus() {
	cds := models.GetCDs(models.Cd{DeployResult: "true"})
	for _, cd := range cds {
		resp, err := d.GetGroupDetail(cd.GroupId)
		if err != nil {
			continue
		}
		status := resp.Response.Result.Status
		if status != nil && *status == "Running" {
			models.AddCdLog(cd.ID, *status, fmt.Sprintf("部署组 %s %s\n", cd.GroupId, *status))
		}
	}
}

func (d *devOps) GetApplications(appName string, appType string) (*tsf.DescribeApplicationsResponse, error) {
	request := tsf.NewDescribeApplicationsRequest()
	request.SearchWord = &appName
	request.ApplicationType = &appType
	return d.tsfClient.DescribeApplications(request)
}

func (d *devOps) GetContainerGroups(appID string) (*tsf.DescribeContainerGroupsResponse, error) {
	request := tsf.NewDescribeContainerGroupsRequest()
	request.ApplicationId = &appID
	return d.tsfClient.DescribeContainerGroups(request)
}

func (d *devOps) GetGroupDetail(groupID string) (*tsf.DescribeContainerGroupDetailResponse, error) {
	request := tsf.NewDescribeContainerGroupDetailRequest()
	request.GroupId = &groupID
	return d.tsfClient.DescribeContainerGroupDetail(request)
}

func (d *devOps) CreateApplication(appName string, appType string, serviceType string) (*tsf.CreateApplicationResponse, error) {
	request := &tsf.CreateApplicationRequest{
		ApplicationName:  &appName,
		ApplicationType:  &appType,
		MicroserviceType: &serviceType,
	}
	return d.tsfClient.CreateApplication(request)
}
